package com.example.feign.config;

import feign.Feign;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StopWatch;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@ConditionalOnClass(Feign.class)
@AutoConfigureAfter(FeignAutoConfiguration.class)
public class FeignOkHttpConfig {

    @Bean
    public OkHttpClient okHttpClient(){
        return new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS) //设置连接超时
                .readTimeout(30, TimeUnit.SECONDS) //设置读取超时
                .writeTimeout(60, TimeUnit.SECONDS) //设置写入超时
                .retryOnConnectionFailure(true)  //是否自动重连
                .connectionPool(new ConnectionPool())
                .addInterceptor(new OkHttpLogInterceptor())
                .build();
    }
}

@Slf4j
class OkHttpLogInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        StopWatch stopWatch = new StopWatch("OKHttp");
        //请求发起的时间
        stopWatch.start("request");
        log.info(String.format("发送请求 【%s】 在 %s%n%s", request.url(), chain.connection(), request.headers()));
        Response response = chain.proceed(request);

        //收到响应的时间
        stopWatch.stop();

        //不能使用response.body().string()的方式输出日志，因为执行了方法后，流会被关闭
        ResponseBody responseBody = response.peekBody(1024 * 1024);

        log.info(String.format("接收响应：【%s】 %n返回json:【%s】 %dms%n%s", response.request().url(),
                responseBody.string(), stopWatch.getTotalTimeMillis(), response.headers()));
        return response;
    }
}
